import RobotoMonoBold from "@/assets/roboto-mono-700.ttf"; import RobotoMono from "@/assets/roboto-mono-regular.ttf"; import { getAllPosts } from "@/data/post"; import { siteConfig } from "@/site.config"; import { getFormattedDate } from "@/utils/date"; import { Resvg } from "@resvg/resvg-js"; import type { APIContext, InferGetStaticPropsType } from "astro"; import satori, { type SatoriOptions } from "satori"; import { html } from "satori-html"; const ogOptions: SatoriOptions = { // debug: true, fonts: [ { data: Buffer.from(RobotoMono), name: "Roboto Mono", style: "normal", weight: 400, }, { data: Buffer.from(RobotoMonoBold), name: "Roboto Mono", style: "normal", weight: 700, }, ], height: 630, width: 1200, }; const markup = (title: string, pubDate: string) => html`

${pubDate}

${title}

${siteConfig.title}

by ${siteConfig.author}

`; type Props = InferGetStaticPropsType; export async function GET(context: APIContext) { const { pubDate, title } = context.props as Props; const postDate = getFormattedDate(pubDate, { month: "long", weekday: "long", }); const svg = await satori(markup(title, postDate), ogOptions); const png = new Resvg(svg).render().asPng(); return new Response(png, { headers: { "Cache-Control": "public, max-age=31536000, immutable", "Content-Type": "image/png", }, }); } export async function getStaticPaths() { const posts = await getAllPosts(); return posts .filter(({ data }) => !data.ogImage) .map((post) => ({ params: { slug: post.id }, props: { pubDate: post.data.updatedDate ?? post.data.publishDate, title: post.data.title, }, })); }